home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / Tool Chest / Development Platforms / AppsToGo / AppsToGo.src / FontTester / Window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-18  |  23.2 KB  |  753 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        Window.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1993 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11. /* You may incorporate this sample code into your applications without
  12. ** restriction, though the sample code has been provided "AS IS" and the
  13. ** responsibility for its operation is 100% yours.  However, what you are
  14. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  15. ** after having made changes. If you're going to re-distribute the source,
  16. ** we require that you make it clear in the source that the code was
  17. ** descended from Apple Sample Code, but that you've made changes. */
  18.  
  19. /* This file contains the code for the document procedure pointers for the main Wannabe
  20. ** document.  Wannabe currently only supports one type of documents, type 'DUMD',
  21. ** which stands for "DUMb Document". */
  22.  
  23. /* For more information on this file, please read the read.me file "=How to write your app". */ 
  24.  
  25.  
  26.  
  27. /*****************************************************************************/
  28.  
  29.  
  30.  
  31. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  32. #include "App.defs.h"        /* Get various application definitions.            */
  33. #include "App.protos.h"        /* Get the prototypes for application.            */
  34.  
  35. #ifndef __ERRORS__
  36. #include <Errors.h>
  37. #endif
  38.  
  39. #ifndef __FONTS__
  40. #include <Fonts.h>
  41. #endif
  42.  
  43. #ifndef __RESOURCES__
  44. #include <Resources.h>
  45. #endif
  46.  
  47. #ifndef __TOOLUTILS__
  48. #include <ToolUtils.h>
  49. #endif
  50.  
  51. #ifndef __UTILITIES__
  52. #include "Utilities.h"
  53. #endif
  54.  
  55.  
  56.  
  57. /*****************************************************************************/
  58.  
  59.  
  60.  
  61. Boolean        gNoDefaultDocument = false;
  62.                     /* Set to true if app should boot with no default document. */
  63.                     /* This tells DTS.Lib..framework what you want. */
  64.  
  65. OSType        gAppWindowType = kDocFileType;    /* Main document type. */
  66. long        gAppWindowAttr = kwAppWindow;    /* Main window attributes. */
  67.  
  68. short        gMinVersion    = kMinVersion;    /* Minimum document version app can support. */
  69. short        gMaxVersion    = kMaxVersion;    /* Maximum document version app can support. */
  70.                                             /* More informing DTS.Lib..framework. */
  71.  
  72. extern Boolean        gQuitApplication;
  73. extern short        gPrintPage;                /* Non-zero means we are printing. */
  74.                                             /* DTS.Lib..framework global. */
  75.  
  76. extern RgnHandle    gCursorRgn;                /* We handle cursors here, so we need */
  77. extern CursPtr        gCursorPtr;                /* to know about these things. */
  78.                                             /* Above are DTS.Lib..framework globals. */
  79.  
  80. static void    TestDisplay(WindowPtr window);
  81.  
  82. /* Currently Wannabe doesn't ever change the cursor, so we don't actually need
  83. ** these referenced here.  However, since Wannabe is supposed to be an application
  84. ** in progress, it is very likely that you will need to reference these as your
  85. ** project develops.  See DTS.Chat and DTS.Draw for examples of setting the cursor. */
  86.  
  87. /* Some cursors are pointer-based, and some cursors are resource-based.
  88. ** If a cursor is resource-based, it needs to be loaded and made to not move,
  89. ** and then gCursorPtr can be set to point to it.  This makes all cursors
  90. ** pointer-based.  Also, gCursorPtr is used by DTS.Lib..framework to
  91. ** determine if there is a current cursor.  If gCursorPtr is nil, then
  92. ** there is no current cursor, and the cursor has to be recalculated, no
  93. ** matter where the mouse is.  If gCursorPtr is not nil, then if the
  94. ** mouse position is within the cursor region gCursorRgn, the cursor is
  95. ** correct, and no recalculation is necessary.  If it is outside this region,
  96. ** then it is recalculated.  What does this all mean?  It means that if you
  97. ** want to guarantee that the cursor is recalculated next time DoWindowCursor()
  98. ** is called, set gCursorPtr to nil.
  99. **
  100. ** If you have a cursor resource, you need to:
  101. ** 1) Load the resource.
  102. ** 2) Make a fixed copy of it.
  103. ** 3) Set the cursor to it.
  104. ** 4) Set gCursorPtr to point to the fixed copy.
  105. **
  106. ** There is a function that does almost all of this, called DoSetResCursor().
  107. ** It does all but set gCursorPtr to it.  (It actually sets gCursorPtr to nil.)
  108. ** It does return a pointer to the permanent copy, so typically what you will
  109. ** want to do is the following:
  110. **     gCursorPtr = DoSetResCursor(theCursorID);
  111. **
  112. ** So why set gCursorPtr to nil as the default action?  This allows you to
  113. ** set a temporary cursor, which will be replaced when DoWindowCursor() is
  114. ** called next, or it allows you to set a cursor that maps to the cursor
  115. ** region gCursorRgn (by setting gCursorPtr to the return result). */
  116.  
  117.  
  118.  
  119. /*****************************************************************************/
  120. /*****************************************************************************/
  121.  
  122.  
  123.  
  124. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  125.  
  126. /* Calculate application specific frame area (Called by DoCalcFrameRgn).
  127. ** You are passed an empty region.  You are supposed to add any custom frame
  128. ** parts that this document uses.  Typically there are no frame portions, as
  129. ** they are accounted for in other ways.  The scrollbars and grow icon will
  130. ** automatically be contributed to the calculation of the frame region.
  131. ** If you use sidebars, these are also added in automatically.  This is only
  132. ** used if the frame region is more complicated than can automatically be
  133. ** handled.  So, almost always, you will simply leave the region empty. */
  134.  
  135. #pragma segment TheDoc
  136. void    CalcFrameRgn(FileRecHndl frHndl, WindowPtr window, RgnHandle rgn)
  137. {
  138. #pragma unused (frHndl, window, rgn)
  139. }
  140.  
  141.  
  142.  
  143. /*****************************************************************************/
  144.  
  145.  
  146.  
  147. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  148.  
  149. /* This is called (by DoContentClick()) when a mouse-down event occurs in the content of
  150. ** a window.  Other applications might want to call FindControl, TEClick, etc., to
  151. ** further process the click. */
  152.  
  153. #pragma segment TheDoc
  154. void    ContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
  155. {
  156. #pragma unused (firstClick)
  157.  
  158.     ControlHandle    ctl;
  159.     short            action, cnum;
  160.     FileRecHndl        frHndl;
  161.  
  162.     cnum = IsCtlEvent(window, event, &ctl, &action);
  163.     if (cnum > 0) {
  164.         frHndl = (FileRecHndl)GetWRefCon(window);
  165.         (*frHndl)->d.doc.newImage = true;
  166.         BeginContent(window);
  167.         DoImageDocument(frHndl);
  168.         EndContent(window);
  169.         SetDocSize(frHndl, kwNoChange, (*frHndl)->d.doc.docSize);
  170.     }    
  171.     return;
  172. }
  173.  
  174.  
  175.  
  176. /*****************************************************************************/
  177.  
  178.  
  179.  
  180. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  181.  
  182. /* DoKeyDown() is first called by the application.  Then if the key isn't a menu
  183. ** key, DoKeyDown() calls this code.  Here are the rules for this function:
  184. **
  185. ** 1) If you handle the key, return(true).  This completes the key handling.
  186. ** 2) If you don't handle the key, you return false.  However, there are two
  187. **    situations for not handling the key:
  188. **      a) You want someone else to.
  189. **      b) You want nobody else to look at the key.
  190. **    This is what the boolean passThrough is for.  If you wish the next window
  191. **    to have a look at the key, set the boolean passThrough to true.  passThrough
  192. **    is already initialized to false, which is the common case, so you only have
  193. **    to worry about setting it true.
  194. **
  195. ** If you have a window that never processes keys and always passes them through,
  196. ** just set the contentKeyProc to nil.  This will indicate to the application
  197. ** framework that all keys should be passed through this window.  DTS.Draw has
  198. ** such a window.  Its palette window doesn't accept keys.  They are passed through
  199. ** to document windows. */
  200.  
  201. #pragma segment TheDoc
  202. Boolean    ContentKey(WindowPtr window, EventRecord *event, Boolean *passThrough)
  203. {
  204. #pragma unused (passThrough)
  205.  
  206.     short    cnum;
  207.  
  208.     cnum = IsCtlEvent(window, event, nil, nil);
  209.         /* See DTS.Draw for an example of what you might do here. */
  210.  
  211.     return(true);
  212. }
  213.  
  214.  
  215.  
  216. /*****************************************************************************/
  217.  
  218.  
  219.  
  220. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  221.  
  222. /* Draw application specific content (Called by DoDrawFrame).
  223. **
  224. ** If your application has any custom frame areas, or if it uses sidebars,
  225. ** this is the function that you would put the frame drawing code.  The
  226. ** document scrollbars and grow icon drawing is handled by DTS.framework.
  227. ** Just do the sidebar and custom areas here. */
  228.  
  229. #pragma segment TheDoc
  230. void    DrawFrame(FileRecHndl frHndl, WindowPtr window, Boolean activate)
  231. {
  232.     Str255    str;
  233.  
  234.     MoveTo(0, (*frHndl)->fileState.topSidebar - 1);
  235.     LineTo((*frHndl)->fileState.leftSidebar - 1 - 16384, (*frHndl)->fileState.topSidebar - 1);
  236.     LineTo((*frHndl)->fileState.leftSidebar - 1 - 16384, 16383);
  237.  
  238.     BeginFrame(window);
  239.  
  240.     MoveTo(0, 0);
  241.     Line(100,100);
  242.     TextFont(systemFont);
  243.     pcpy(str, (*frHndl)->d.doc.fontName);
  244.     DrawString(str);
  245.  
  246.     DoDrawControls(window, activate);
  247.     
  248.     EndFrame(window);
  249. }
  250.  
  251.  
  252.  
  253. /*****************************************************************************/
  254.  
  255.  
  256.  
  257. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  258.  
  259. /* Frees up any application-specific memory in the document.  This is called by
  260. ** DoFreeDocument, which is called by DisposeDocument().  The application would
  261. ** call DisposeDocument(), not DoFreeDocument() or FreeDocument() directly.
  262. **
  263. ** The document may have a bunch of handles off the main handle of the document.
  264. ** This is where they are freed.  DisposeDocument calls this prior to releasing
  265. ** the ram for the main handle of the document, so release everything else
  266. ** here, or you will have a memory leak.
  267. **
  268. ** NOTE:  Calling DefaultFreeDocument() frees up all memory used by a
  269. ** hierarchical document (see TreeObj package). */
  270.  
  271. #pragma segment TheDoc
  272. OSErr    FreeDocument(FileRecHndl frHndl)
  273. {
  274.     return(DefaultFreeDocument(frHndl));
  275. }
  276.  
  277.  
  278.  
  279. /*****************************************************************************/
  280.  
  281.  
  282.  
  283. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  284.  
  285. /* Any additional window disposal tasks can be handled here. */
  286.  
  287. #pragma segment TheDoc
  288. OSErr    FreeWindow(FileRecHndl frHndl, WindowPtr window)
  289. {
  290. #pragma unused (frHndl, window)
  291.  
  292.     return(noErr);
  293. }
  294.  
  295.  
  296.  
  297. /*****************************************************************************/
  298.  
  299.  
  300.  
  301. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  302.  
  303. /* Image the document into the current port.
  304. **
  305. ** The only thing tricky about this function is that it needs to key off of
  306. ** the global variable gPrintPage.  gPrintPage is the current page that is
  307. ** being printed.  If gPrintPage is 0, then you are drawing to the window.
  308. **
  309. ** For when printing:
  310. **
  311. ** If gPrintPage is non-0, that is the page to be printed.  If after imaging
  312. ** the page there are no more pages, you should set gPrintPage to 0.  This
  313. ** indicates to the print loop that the end of the document has been reached.
  314. ** Even if the user indicated in the job dialog to print more pages, setting
  315. ** gPrintPage to 0 states that the last page has been printed.  This is necessary
  316. ** because the print loop can't know when printing is done.  The imaging procedure
  317. ** is the logical one to state when everything has been imaged. */
  318.  
  319. #pragma segment TheDoc
  320. OSErr    ImageDocument(FileRecHndl frHndl)
  321. {
  322. #pragma unused (frHndl)
  323.  
  324.     WindowPtr    curPort;
  325.  
  326.     GetPort(&curPort);
  327.     if (!gPrintPage) {                                    /* If not printing... */
  328.         DoDrawControls(curPort, false);                    /* Draw the content controls. */
  329.     }
  330.  
  331.     TestDisplay((*frHndl)->fileState.window);
  332.  
  333.     gPrintPage = 0;
  334.  
  335.     return(noErr);
  336. }
  337.  
  338.  
  339.  
  340. /*****************************************************************************/
  341.  
  342.  
  343.  
  344. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  345.  
  346. /* This function does the remaining window initialization.
  347. **
  348. ** There may be additional content initialization for the window.  At this point,
  349. ** you have a window, but it is currently invisible.  If you return noErr, then
  350. ** the window will be set to the state indicated for that window.  Why this function?
  351. ** You may wish to add controls to the content of the window.  You may have a
  352. ** TextEdit record in the content.  All of these sort of things can't be created
  353. ** until there is a window to contain them.  First a document is read in, and then
  354. ** if the document creation succeeds, a window is created for that document.
  355. ** At this point we have a document, and we are on our way to having a window.
  356. ** All that remains is any additional content initialization.  Do it, return
  357. ** noErr, and everybody's happy.  If something goes wrong here, return the error,
  358. ** and the incomplete window will be disposed of. */
  359.  
  360. #pragma segment TheDoc
  361. OSErr    InitContent(FileRecHndl frHndl, WindowPtr window)
  362. {
  363.     OSErr            err;
  364.     WindowPtr        ww;
  365.     ControlHandle    ctl;
  366.     Str255            str;
  367.     MenuHandle        menu;
  368.     short            i, mark;
  369.  
  370.     err = AddControlSet(window, (*frHndl)->fileState.sfType, kwStandardVis, 0, 0, nil);
  371.  
  372.     ww = GetNextWindow(nil, 'STGS');
  373.         /* The 'STGS' window is created at startup initially invisible,
  374.         ** and just hide on close, so we can reference the controls and
  375.         ** their contents at this point. */
  376.  
  377.     CNum2Ctl(ww, 101, &ctl);
  378.     CTEGetPStr(ctl, str);
  379.     pcpy((*frHndl)->d.doc.testStr, str);
  380.         /* Get the initial string out of the control for drawing to test windows. */
  381.  
  382.     CNum2Ctl(ww, 102, &ctl);
  383.     CTEGetPStr(ctl, str);
  384.     (*frHndl)->d.doc.minSize = p2dec(str, nil);
  385.  
  386.     CNum2Ctl(ww, 103, &ctl);
  387.     CTEGetPStr(ctl, str);
  388.     (*frHndl)->d.doc.maxSize = p2dec(str, nil);
  389.  
  390.     menu = GetMHandle(mFont);
  391.     for (i = CountMItems(menu); (i > 1); --i) {
  392.         GetItemMark(menu, i, &mark);
  393.         if (mark != noMark) break;
  394.     }
  395.     GetItem(menu, i, str);
  396.     pcpy((*frHndl)->d.doc.fontName, str);
  397.  
  398.     CNum2Ctl(ww, -1, &ctl);
  399.     if ((*ctl)->contrlHilite == 255) {
  400.         (*ctl)->contrlHilite = 0;
  401.         DoDraw1Control(ctl, false);
  402.     }
  403.  
  404.     return(err);
  405. }
  406.  
  407.  
  408.  
  409.  
  410.  
  411. /*****************************************************************************/
  412.  
  413.  
  414.  
  415. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  416.  
  417. /* The code below assumes that you are using the hierarchical document package.
  418. ** If you are, the entire hierarchical document is read in with just these two
  419. ** calls.  If you don't use it, you are on your own.  See DTS.Chat for an
  420. ** example of an application that uses the DTS.framework without the hierarchical
  421. ** document package. */
  422.  
  423. #pragma segment TheDoc
  424. OSErr    ReadDocument(FileRecHndl frHndl)
  425. {
  426.     OSErr    err;
  427.  
  428.     err = DefaultReadDocument(frHndl);
  429.     if (!err)
  430.         DefaultReadDocumentFixup(frHndl);
  431.  
  432.     return(err);
  433. }
  434.  
  435.  
  436.  
  437. /*****************************************************************************/
  438.  
  439.  
  440.  
  441. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  442.  
  443. /* Resize application specific content (Called by ResizeWindow).
  444. **
  445. ** This gets called when a user does a zoom or window resizing operation.
  446. ** It is possible that things in the content need to be resized in conjunction
  447. ** with the resizing of the window. */
  448.  
  449. #pragma segment TheDoc
  450. void    ResizeContent(WindowPtr window, short oldh, short oldv)
  451. {
  452. #pragma unused (window, oldh, oldv)
  453.  
  454.     /* See DTS.Chat for a sample usage of this function. */
  455. }
  456.  
  457.  
  458.  
  459. /*****************************************************************************/
  460.  
  461.  
  462.  
  463. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  464.  
  465. /* Scroll application specific frame (Called by DoScrollFrame).
  466. **
  467. ** Some applications may need to scroll the "frame" of the document along
  468. ** with the document contents.  This is common for applications with rulers,
  469. ** or other similar sidebar items. */
  470.  
  471. #pragma segment TheDoc
  472. void    ScrollFrame(FileRecHndl frHndl, WindowPtr window, long dh, long dv)
  473. {
  474. #pragma unused (frHndl, window, dh, dv)
  475. }
  476.  
  477.  
  478.  
  479. /*****************************************************************************/
  480.  
  481.  
  482.  
  483. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  484.  
  485. /* Since the hierarchical document package isn't used by DTS.Chat,
  486. ** this function actually never gets called. */
  487.  
  488. #pragma segment TheDoc
  489. void    UndoFixup(FileRecHndl frHndl, Point contOrg, Boolean afterUndo)
  490. {
  491. #pragma unused (frHndl, contOrg, afterUndo)
  492.  
  493.     /* See DTS.Draw for an example of what you might do here. */
  494. }
  495.  
  496.  
  497.  
  498. /*****************************************************************************/
  499.  
  500.  
  501.  
  502. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  503.  
  504. /* This function is where you adjust the cursor to reflect the location in the
  505. ** document or window.  You have the additional input of gCursorRgn to deal
  506. ** with.  The way that the cursor handling works is as follows:
  507. ** 1) The application calls DoWindowCursor().
  508. ** 2) DoWindowCursor() works its way through the windows/documents, front to back.
  509. **    It looks at the document's windowCursorProc and checks to see if the document
  510. **    has one.  If the document doesn't have one, then it assumes that that window
  511. **    always wants an arrow.  If the cursor is over that window, the cursor is set
  512. **    to an arrow, and we're done.  If the cursor isn't over the window, then the next
  513. **    window is tried.  If all documents don't have a windowCursorProc, then the cursor
  514. **    is set to an arrow (for the non-document area of the screen).
  515. ** 3) If a document has a windowCursorProc, then the proc is called.  The proc's
  516. **    job is as follows:
  517. **    a) If the cursor is over a position that is determined by the window, then
  518. **       the proc removes other areas from gCursorRgn.  Note that it should not
  519. **       simply set the area to what it "thinks" is the correct area.  This window
  520. **       may not be the front-most.  Other windows will have already been subtracted
  521. **       from gCursorRgn.  The resultant gCursorRgn is the correct cursor area,
  522. **       and should be passed to WaitNextEvent calls in the application (already the case
  523. **       in EventLoop.c).  Also, the cursor should be set to the correct cursor, of course.
  524. **       You should also return true, as the cursor has been determined.
  525. **    b) If the cursor is not over a position for this window, then you should
  526. **       return.  You will either pass back true or false.  If you don't wish
  527. **       windows behind this window to have a shot at cursor determination, then
  528. **       return true.  This states that the cursor is "determined".  It is, in the
  529. **       sense that no further determination will occur.  If you return false, then
  530. **       other windows get a shot at determining the cursor.
  531. **
  532. ** Setting the cursor to the correct cursor isn't as easy as you would expect.
  533. ** DTS.Lib..framework uses the global gCursorPtr as the reference to the cursor.  This is
  534. ** fine if the cursor is pointer-based, but if the cursor is resource-based, it is a bit
  535. ** more of a problem.  What you will need to do is to call DoSetResCursor() to make the
  536. ** resource cursor pointer-based.  DoSetResCursor() will set gCursorPtr to nil, and it
  537. ** also returns the pointer to the permanent copy of the cursor resource.  Just set gCursorPtr
  538. ** to the return result of DoSetResCursor(), and you will be set. */
  539.  
  540. #pragma segment TheDoc
  541. Boolean    WindowCursor(FileRecHndl frHndl, WindowPtr window, Point globalPt)
  542. {
  543. #pragma unused (frHndl, window, globalPt)
  544.  
  545.     /* For examples of applications that have non-arrow cursor regions,
  546.     ** see DTS.Chat and DTS.Draw. */
  547.  
  548.     DoSetCursor(&qd.arrow);
  549.     return(true);
  550. }
  551.  
  552.  
  553.  
  554. /*****************************************************************************/
  555.  
  556.  
  557.  
  558. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  559.  
  560. /* After the DTS.Lib framework disposes of a window, it calls here.  This is
  561. ** to give the application a chance to do any additional tasks related to
  562. ** a window closing.  DTS.Chat doesn't have anything else extra to do. */
  563.  
  564. #pragma segment TheDoc
  565. void    WindowGoneFixup(WindowPtr window)
  566. {
  567.     ControlHandle    ctl;
  568.  
  569.     if (!GetNextWindow(nil, kDocFileType)) {
  570.         window = GetNextWindow(nil, 'STGS');
  571.         CNum2Ctl(window, -1, &ctl);
  572.         if ((*ctl)->contrlHilite != 255) {
  573.             (*ctl)->contrlHilite = 255;
  574.             DoDraw1Control(ctl, false);
  575.         }
  576.     }
  577. }
  578.  
  579.  
  580.  
  581. /*****************************************************************************/
  582.  
  583.  
  584.  
  585. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  586.  
  587. /* The reverse function of ReadDocument. */
  588.  
  589. #pragma segment TheDoc
  590. OSErr    WriteDocument(FileRecHndl frHndl)
  591. {
  592.     return(DefaultWriteDocument(frHndl));
  593. }
  594.  
  595.  
  596.  
  597. /*****************************************************************************/
  598.  
  599.  
  600.  
  601. /* •• You don't call this.  DTS.Lib..framework does at open-application time. •• */
  602.  
  603. #pragma segment TheDoc
  604. OSErr    DoOpenApplication(void)
  605. {
  606.     MenuHandle    menu;
  607.  
  608.     menu = GetMHandle(mFont);
  609.     if (menu) {
  610.         AddResMenu(menu, 'FONT');
  611.         CheckItem(menu, 1, true);
  612.     }
  613.  
  614.     return(noErr);
  615. }
  616.  
  617.  
  618.  
  619. /*****************************************************************************/
  620. /*****************************************************************************/
  621. /*****************************************************************************/
  622.  
  623.  
  624.  
  625. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  626.  
  627. Boolean    DoAdjustFontMenu(WindowPtr window);
  628.  
  629. #pragma segment TheDoc
  630. Boolean    AdjustMenuItems(WindowPtr window, short menuID)
  631. {
  632.     Boolean        redrawMenuBar;
  633.     MenuHandle    menu;
  634.  
  635.     redrawMenuBar = false;
  636.  
  637.     switch (menuID) {
  638.         case mFile:
  639.             redrawMenuBar = DoAdjustFileMenu(window);
  640.             break;
  641.         case mEdit:
  642.             redrawMenuBar = DoAdjustEditMenu(window);
  643.             break;
  644.         case mFont:
  645.             redrawMenuBar = DoAdjustFontMenu(window);
  646.             break;
  647.         case mOptions:
  648.             if (FrontWindow() == GetNextWindow(nil, kDocFileType))
  649.                 if (menu = GetMHandle(menuID))
  650.                     (*menu)->enableFlags |= 0xFFFFFFFEL;
  651.             break;
  652.         default:
  653.             if (menu = GetMHandle(menuID))
  654.                 (*menu)->enableFlags |= 0xFFFFFFFEL;
  655.             break;
  656.     }
  657.  
  658.     return(redrawMenuBar);
  659. }
  660.  
  661.  
  662.  
  663. /*****************************************************************************/
  664.  
  665.  
  666.  
  667. /* •• You don't call this.  DTS.Lib..framework does for appropriate document type(s). •• */
  668.  
  669. #pragma segment TheDoc
  670. Boolean    DoMenuItem(WindowPtr window, short menuID, short menuItem)
  671. {
  672. #pragma unused (window)
  673.  
  674.     return(DoMenuCommand(menuID, menuItem));
  675. }
  676.  
  677.  
  678.  
  679. /*****************************************************************************/
  680. /*****************************************************************************/
  681. /*****************************************************************************/
  682.  
  683.  
  684.  
  685. #pragma segment TheDoc
  686. static void    TestDisplay(WindowPtr window)
  687. {
  688.     FileRecHndl        frHndl;
  689.     Str255            str;
  690.     short            size, w, y, dy;
  691.     short            familyID;
  692.     ControlHandle    ctl;
  693.     FontInfo        info;
  694.     Rect            rct;
  695.  
  696.     frHndl = (FileRecHndl)GetWRefCon(window);
  697.  
  698.     if ((*frHndl)->d.doc.newImage) {
  699.         EraseRect(&(window->portRect));
  700.         (*frHndl)->d.doc.newImage = false;
  701.     }
  702.  
  703.     pcpy(str, (*frHndl)->d.doc.fontName);
  704.     GetFNum(str, &familyID);
  705.  
  706.     CNum2Ctl(window, 101, &ctl);
  707.     SetFractEnable((*ctl)->contrlValue);
  708.  
  709.     CNum2Ctl(window, 102, &ctl);
  710.     SetFScaleDisable((*ctl)->contrlValue);
  711.  
  712.     CNum2Ctl(window, 103, &ctl);
  713.     SetOutlinePreferred((*ctl)->contrlValue);
  714.  
  715.     y = 0;
  716.     info.descent = 0;
  717.  
  718.     for (size = (*frHndl)->d.doc.minSize; size <= (*frHndl)->d.doc.maxSize; size++) {
  719.         TextSize(size);
  720.         TextFont(familyID);
  721.         GetFontInfo(&info);
  722.         dy = info.ascent + info.descent + info.leading;
  723.         if (dy < 20) 
  724.             dy = 20;
  725.         y = y + dy;
  726.         MoveTo(8, y);
  727.         pcpy(str, (*frHndl)->d.doc.testStr);
  728.         DrawString(str);
  729.         w = StringWidth(str); 
  730.  
  731.         TextSize(12);
  732.         TextFont(systemFont);
  733.         pcpydec(str, size);
  734.         MoveTo(380 - StringWidth(str), y );
  735.         DrawString(str);
  736.         
  737.         pcpydec(str, w);
  738.         MoveTo(450 - StringWidth(str), y );
  739.         DrawString(str);
  740.  
  741.     }
  742.  
  743.     y += info.descent;
  744.     SetRect(&rct, 0, y, window->portRect.right, window->portRect.bottom);
  745.     EraseRect(&rct);
  746.  
  747.     y += 10;
  748.     (*frHndl)->d.doc.docSize = y;
  749. }
  750.  
  751.  
  752.  
  753.